package com.zst.bluetooth.utils;

import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Created by zhang on 2016/3/16 0016. 蓝牙操作工具类
 */
public class BlueToothUtils {

    private static BluetoothAdapter bluetoothAdapter;
    private static BluetoothDevice mDevice;
    private static BluetoothSocket socket;
    private static CountDownLatch begin;
    private static CountDownLatch end;
    private static String re = "设备长时间没有返回";
    private static ReadTask task = new ReadTask(new TaskInfo() {
        @Override
        public void onPre() {
        }

        @Override
        public void onFinish(String result) {
            re = result;
        }
    });

    /**
     * 获取已配对过的设备列表,并开始发现其他蓝牙设备
     *
     * @return 已经配对的蓝牙设备列表, 如果返回的list的size为0, 表示没有已配对过的蓝牙设备
     */
    public static List<String> find() {
        //开始发现其他蓝牙设备,要在主界面监听蓝牙搜索状态
        bluetoothAdapter.startDiscovery();
        List<String> devices = new ArrayList<>();
        //获取已经配对的蓝牙设备
        Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
        //存在已经配对过的蓝牙设备
        if (bondedDevices.size() > 0) {
            //遍历以配对的蓝牙设备,并将其信息存入list
            for (BluetoothDevice btd : bondedDevices) {
                devices.add(btd.getName() + "##" + btd.getAddress());
            }
        }
        return devices;
    }

    /**
     * 停止查找设备
     */
    public static void stopFind() {
        //如果正在查找,则停止
        if (bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
    }

    /**
     * 打开/连接蓝牙设备 这是一个耗时操作,建议放在一个Thread中执行
     *
     * @param addr 要连接的设备的地址
     * @return true:已连接 false:连接失败
     * @throws BlueException 连接时出现异常
     */
    public static boolean open(String addr) throws BlueException {
        if (isOpen())//如果已经打开,先关闭,一次只连接一个设备
            close();
        //获取远程设备
        mDevice = bluetoothAdapter.getRemoteDevice(addr);
        //获取接口

        //如果没有配对,则配对
        if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) {
            try {
                Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
                createBondMethod.invoke(mDevice);
            } catch (Exception e) {
                throw new BlueException("配对时出现异常");
            }
        }

        try {
            //uuid是固定的
            socket = mDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
            socket.connect();//耗时操作
        } catch (IOException e) {
            throw new BlueException("打开蓝牙连接时异常");
        }
        //开始连接
        return socket.isConnected();
    }

    public static boolean isOpen() {
        return null != socket && socket.isConnected();
    }

    /**
     * 关闭连接
     */
    public static void close() {
        if (isOpen())
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        socket = null;
    }

    /**
     * 发送数据,这是一个阻塞式的方法,建议放在Task中使用,当执行完成后会结束阻塞,
     *
     * @param msg 要发送的数据
     * @throws BlueException 发送和接收数据时出现的异常,
     */
    public static void sendMsg(String msg) throws BlueException {
        if (socket == null) {//如果没有连接,提示用户
            throw new BlueException("请先连接");
        }
        synchronized (socket) {
            try {//发送消息,消息编码为GBK
                OutputStream os = socket.getOutputStream();
                os.write(msg.getBytes("GBK"));
            } catch (IOException e) {
                throw new BlueException("发送数据时出现异常");
            }
            //结果

            begin = new CountDownLatch(1);
            //读取返回值
            task = new ReadTask(new TaskInfo() {
                @Override
                public void onPre() {
                }

                @Override
                public void onFinish(String result) {
                    re = result;
                }
            });
            task.start();//开始读取任务
            begin.countDown();
            end = new CountDownLatch(1);
            try {
                end.await(10, TimeUnit.SECONDS);//等待10s时间,当end的count值变为0,或者超时时间到都会向下执行
                end.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!re.equals("OK"))
                throw new BlueException(re);
            task.interrupt();
            task = null;
        }
    }

    public static BluetoothAdapter getAdapter() {
        return bluetoothAdapter;
    }

    /**
     * 初始化蓝牙
     */
    public static void initBluetooth(Context context) {
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter != null) {  //设备支持蓝牙
            //确认开启蓝牙
            if (!bluetoothAdapter.isEnabled()) {
                //使蓝牙设备可见，方便配对
                Intent in = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                in.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200);
                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(in);
                //直接开启，不经过提示
                bluetoothAdapter.enable();
            }
        } else {   //设备不支持蓝牙 提示用户
            AlertDialog.Builder dialog = new AlertDialog.Builder(context);
            dialog.setTitle("不是蓝牙设备");
            dialog.setMessage("您的设备不支持蓝牙，请更换设备");

            dialog.setNegativeButton("我知道了",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    });
            dialog.show();
        }
    }

    private static class ReadTask extends Thread {

        private TaskInfo info;

        public ReadTask() {
        }

        public ReadTask(TaskInfo info) {
            this.info = info;
        }

        @Override
        public void run() {
            boolean isReceive = false;
            String receive;
            try {
                begin.await();
                do {
                    byte[] buffer = new byte[1024];
                    int bytes;
                    InputStream mmInStream = null;
                    try {
                        mmInStream = socket.getInputStream();//获取读取消息输入流
                        // Read from the InputStream
                        //循环读取返回值,如果能读取到,则判断是否是正确的值
                        if ((bytes = mmInStream.read(buffer)) > 0) {
                            byte[] buf_data = new byte[bytes];
                            System.arraycopy(buffer, 0, buf_data, 0, bytes);
                            //将读取到的数组转化为字符
                            receive = new String(buf_data, "GBK");//以GBK方式读取
                            //判读返回值是否正确
                            if (receive.toUpperCase().equals(new String(new byte[]{75}, "GBK"))) {
                                isReceive = true;//如果正确,退出循环
                                if (null != info)
                                    info.onFinish("OK");//完成
                            } else {
                                isReceive = true;
                                if (null != info)
                                    info.onFinish("返回码错误,请检查设备返回码是否正确");
                            }
                        }
                    } catch (IOException e) {
                        Log.i("", "run-e: " + e.toString());
                        try {
                            if (mmInStream != null)
                                mmInStream.close();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        if (null != info)
                            info.onFinish("接收消息时出现异常,请重试");
                        isReceive = true;
                    }
                } while (!isReceive && end.getCount() > 0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                end.countDown();
            }
        }

        /**
         * 设置任务完成监听
         *
         * @param info 任务监听器
         */
        public void setTaskInfo(TaskInfo info) {
            this.info = info;
        }
    }
}
